package com.example.sbbsec;

import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;



/**
 * Created by Arat.Wu on 2018/12/04.
 */
public class FuctionalMethods2 {



    /**
     * 简单合并
     * @param firstList
     * @param secondList
     * @param getKeyFunction
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> List<T> mergeListCommon(List<T> firstList,
                                                 List<T> secondList,
                                                 Function<T, ? extends K> getKeyFunction) {
        final Map<K, T> secondListMap = secondList.stream().collect(Collectors.toMap(getKeyFunction, y -> y));
        final Map<K, T> firstListMap = firstList.stream().collect(Collectors.toMap(getKeyFunction, y -> y));
        firstListMap.putAll(secondListMap);
        return firstListMap.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
    }

    /**
     * 遍历合并
     * @param firstList
     * @param secondList
     * @param getKeyFunction
     * @param mergeFuction
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T, K> List<T> mergeListCommon2(List<T> firstList,
                                                  List<T> secondList,
                                                  Function<T, ? extends K> getKeyFunction,
                                                  BinaryOperator<Map<K, T>> mergeFunction) {
        final Map<K, T> secondListMap = secondList.stream().collect(Collectors.toMap(getKeyFunction, y -> y));
        final Map<K, T> firstListMap = firstList.stream().collect(Collectors.toMap(getKeyFunction, y -> y));
        final Map<K, T> resultMap = mergeFunction.apply(firstListMap, secondListMap);
        return resultMap.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
    }

    public static <T, K> List<T> mergeListCommon3(List<T> firstList,
                                                  List<T> secondList,
                                                  Function<T, ? extends K> getKeyFunction) {
        final Map<K, T> secondListMap = secondList.stream().collect(Collectors.toMap(getKeyFunction, y -> y));
        final Map<K, T> firstListMap = firstList.stream().collect(Collectors.toMap(getKeyFunction, y -> y));
        BinaryOperator<Map<K, T>> mergeFunction =(v1,v2)-> {
            v1.forEach((key, city) -> {
                if (v2.containsKey(key)) {
                    v2.put(key, city);
                } else {
                    v2.put(key, city);
                }
            });
            return v2;
        };
        return mergeFunction.apply(firstListMap,secondListMap).entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
    }



    public static <T, R, K> List<R> mergeList(List<T> firstList,
                                              List<T> secondList,
                                              Function<T, ? extends K> getKeyFunction,
                                              Function<T, ? extends T> getValueFunction,
                                              Function<List<T>, List<R>> mergeFunction) {
        final Map<K, T> secondListMap = secondList.stream().collect(Collectors.toMap(getKeyFunction, getValueFunction));

        firstList.forEach(city -> {
            //获取key
            K key = getKeyFunction.apply(city);
            if (secondListMap.containsKey(key)) {
//                final T t = secondListMap.get(key);
//                final List<Field> fields = Arrays.asList(t.getClass().getFields());
//                fields.stream().

            } else {
                secondListMap.put(key, city);
            }
        });

        return null;
    }

    public static void main(String[] args) {

        final List<City> cities = Arrays.asList(City.builder().id(1L).name("太仓").info("太仓信息").build(),
                City.builder().id(2L).name("沙溪").build());

        final List<City> cities1 = Arrays.asList(City.builder().id(1L).name("太仓").build(),
                City.builder().id(2L).name("沙溪").info("沙溪信息").build(),
                City.builder().id(3L).name("浏河").info("浏河信息").build());

        final Map<Long, List<City>> listMap = cities.stream().collect(Collectors.groupingBy(City::getId));

        final Map<Long, City> longCityMap = cities.stream().collect(Collectors.toMap(City::getId, v -> v));

        final Map<Long, City> longCityMap1 = cities1.stream().collect(Collectors.toMap(City::getId, v -> v));

        BinaryOperator<Map<Long, City>> mergeFunction =(v1,v2)-> {
            v1.forEach((key, city) -> {
                if (v2.containsKey(key)) {
                    if (StringUtils.isEmpty(city.getInfo())) {
                        city.setInfo(v2.get(key).getInfo());
                    }
                    if (StringUtils.isEmpty(city.getName())) {
                        city.setInfo(v2.get(key).getName());
                    }
                    v2.put(key, city);
                } else {
                    v2.put(key, city);
                }
            });
            return v2;
        };
        FuctionalMethods2 fuctionalMethods2 = new FuctionalMethods2();

        List<City> cities3 = mergeListCommon2(cities, cities1,City::getId,mergeFunction);


        List<City> cities4 = mergeListCommon3(cities, cities1,City::getId);


        List<City> cities2 = mergeListCommon(cities, cities1, City::getId);

        System.out.println(cities2);
    }



}
